package c.x.jy.service.aspect;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletResponseWrapper;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder;

import c.x.jy.common.annotation.OrderLock;
import c.x.jy.common.exception.RRException;
import c.x.jy.service.lock.DistributedLock;
import c.x.jy.service.lock.ZLock;
import c.x.jy.service.redis.Cache;
import c.x.jy.service.redis.RedisConstant;
import lombok.extern.slf4j.Slf4j;

@SuppressWarnings("all")
@Aspect
@Configuration
@Slf4j
public class DeviceLockAspect {
 
	   @Autowired
	   private  DistributedLock distributedLock;
	   @Autowired
		private Cache redisUtils;
	 
  
   // @Around("execution(* c.x.jy.*.service.*.*(..)) && @annotation(c.x.jy.common.annotation.OrderLock)")
  //  @Around("execution(* c.x.jy.api.controller.*.*(..)) && @annotation(orderLock)")
    @Around("@annotation(orderLock)")
	public Object   around(ProceedingJoinPoint  joinPoint, OrderLock  orderLock ) throws Throwable {
		    Object result = null;
		     
		   Map map= methodBefore(joinPoint);
		   ZLock lock=null;
		   String deviceNo=null;
		   String openid=null; 
		   try {
			   if(map!=null&&map.containsKey(orderLock.name())&&map.containsKey(orderLock.key())) {
				     deviceNo= map.get(orderLock.name()).toString();
				     openid=map.get(orderLock.key()).toString();
				   lock=	  distributedLock.tryLock(deviceNo, 60, TimeUnit.SECONDS, true);
				   if(lock==null||redisUtils.getSize(RedisConstant.REDISLOCK_KEY+":"+deviceNo+":*")>0)throw new RRException("正在执行中！请稍候...");
					 redisUtils.put(RedisConstant.REDISLOCK_KEY,deviceNo+":"+openid,1, 5*60);
			   }	
		} finally {
			distributedLock.unlock(lock);
		}
		
	 
		try {
		    result = joinPoint.proceed();
		 
		} catch (Exception e) {
			e.printStackTrace();
			 redisUtils.remove(RedisConstant.REDISLOCK_KEY,deviceNo+":"+openid );
			 throw new RRException(e.getMessage());
		}finally {
			if(orderLock.isdel()) redisUtils.remove(RedisConstant.REDISLOCK_KEY,deviceNo+":"+openid );
		}


        return result;
	}
	    
	    
	    
	    private 	Map<String, Object> methodBefore(JoinPoint joinPoint ) {
			Map<String, Object> paramMap =null;
			try {
				// 下面两个数组中，参数值和参数名的个数和位置是一一对应的。
				Object[] objs = joinPoint.getArgs();
				String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); // 参数名
				  paramMap = new HashMap<String, Object>();
				for (int i = 0; i < objs.length; i++) {
					if (!(objs[i] instanceof ExtendedServletRequestDataBinder) && !(objs[i] instanceof HttpServletResponseWrapper)) {
						paramMap.put(argNames[i], objs[i]);
					}
				}
		 
			} catch (Exception e) {
		 
			}
			return paramMap;
		}
 

}
